package com.tianji.promotion.service.impl;

import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.promotion.domain.enums.ExchangeCodeStatus;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.ExchangeCode;
import com.tianji.promotion.domain.po.UserCoupon;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.mapper.UserCouponMapper;
import com.tianji.promotion.service.ICouponScopeService;
import com.tianji.promotion.service.IExchangeCodeService;
import com.tianji.promotion.service.IUserCouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.utils.CodeUtil;
import com.tianji.promotion.utils.MyLock;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 * 用户领取优惠券的记录，是真正使用的优惠券信息 服务实现类
 * </p>
 *
 * @author 优惠卷模块
 * @since 2023-04-22
 */
@Service
@RequiredArgsConstructor
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {


    private final CouponMapper couponMapper;

    private final IExchangeCodeService codeService;

    /**
     * 领取优惠卷
     * @param couponId
     */
    @Override
    public void receiveCoupon(Long couponId) {
        //查询优惠卷
        Coupon coupon = couponMapper.selectById(couponId);

        if (coupon == null){
            throw new BizIllegalException("优惠卷不存在");
        }
        //校验发放时间
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(coupon.getIssueBeginTime()) || now.isAfter(coupon.getIssueEndTime())){
            throw new BizIllegalException("优惠卷发放异常");
        }
        //校验库存
        if (coupon.getIssueNum() >= coupon.getTotalNum()){
            throw new BizIllegalException("库存不足");
        }
        //校验每人限领数量
        //更新优惠卷已经发放的数量 + 1
        //获取用户id
        Long userId = UserContext.getUser();
        //校验限领数量
        //获取分布式锁
        synchronized (userId.toString().intern()) {
            String key = "lock:coupon:uid" + userId;
            IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
            userCouponService.checkAndCreateUserCoupon(coupon, userId);
        }

    }

    @MyLock(name = "lock:coupon")
    @Transactional
    @Override
    public void checkAndCreateUserCoupon(Coupon coupon, Long userId) {
            Integer count = lambdaQuery()
                    .eq(UserCoupon::getUserId, userId)
                    .eq(UserCoupon::getCouponId, coupon.getId())
                    .count();
            //判断已经领取的数量是否大于每人限领的总数量
            if (count != null && count >= coupon.getUserLimit()) {
                throw new BizIllegalException("用户领取次数过多");
            }
            int r = couponMapper.incrIssueNum(coupon.getId());
            if (r == 0) {
                throw new BizIllegalException("用户库存不足");
            }
            //新增一个用户卷
            saveUserCoupor(coupon, userId);
    }


    private void saveUserCoupor(Coupon coupon, Long userId) {
        UserCoupon uc = new UserCoupon();
        uc.setUserId(userId);
        uc.setCouponId(coupon.getId());
        //获取优惠卷开始日期
        LocalDateTime beginTime = coupon.getTermBeginTime();
        //获取优惠卷结束日期
        LocalDateTime endTime = coupon.getTermEndTime();
        //判断领取开始日期
        if (beginTime == null){
            beginTime = LocalDateTime.now();
            endTime = beginTime.plusDays(coupon.getTermDays());
        }
        uc.setTermBeginTime(beginTime);
        uc.setTermEndTime(endTime);
        save(uc);
    }

    /**
     * 兑换码兑换优惠卷接口
     * @param code
     */
    @Override
    @Transactional
    public void CodeCoupon(String code) {
        //校验并解析兑换码
        long serialNum = CodeUtil.parseCode(code);
        //校验是否已经兑换
        boolean exchange = codeService.updateExchangeMark(serialNum,true);
        if (exchange){
            throw new BizIllegalException("兑换码已经兑换过了");
        }
        try {
        //查询兑换码
            ExchangeCode exchangeCode = codeService.getById(serialNum);
            if (exchangeCode == null){
                throw new BizIllegalException("兑换码不存在");
            }
            //是否过期
            LocalDateTime now = LocalDateTime.now();
            if (now.isAfter(exchangeCode.getExpiredTime())){
                throw new BizIllegalException("兑换码已经过期了");
            }
            //获取用户id
            Coupon coupon = couponMapper.selectById(exchangeCode.getExchangeTargetId());
            Long userId = UserContext.getUser();
            //校验限领数量
            checkAndCreateUserCoupon(coupon,userId);
            //更新兑换状态
            codeService.lambdaUpdate()
                    .set(ExchangeCode::getId,coupon.getId())
                    .set(ExchangeCode::getStatus, ExchangeCodeStatus.USED)
                    .set(ExchangeCode::getUserId,userId)
                    .update();

    } catch (Exception e) {
        codeService.updateExchangeMark(serialNum,false);
        throw  e;
    }
    }


}
